#pragma once
#include <string>
#include <vector>
#include <cstring>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fstream>

#define MAXLINE 40960

class Server{
    private:
        enum CL_OPT
        {
            OPT_l,
            OPT_d,
            OPT_NUM
        };
        int                         s_port;
        char const                 *s_address;
        char const                 *s_server_path;
        std::vector<std::string>    s_files;
        bool                        s_show_hidden;
        int                         listenfd, connfd;
        FILE                       *fp;
        char                        recv_buff[MAXLINE];
        char                        send_buff[MAXLINE];
        struct sockaddr_in          s_server_address;
        int                         contain;
        int                         cl_options[OPT_NUM];
        int                         recv_num;
        int                         send_num;


    public:
        Server();
        void            set_port(int new_port);
        void            set_path(char* path);
        void            set_address(char* address);
        void            set_hidden(bool hidden);
        void            get_path_files();
        char const*     get_address();
        int             get_port();

        // start a socket server
        int             create_socket();
        void            init_address();
        int             bind_socket();
        int             listen_socket();
        int             accept_client(struct sockaddr_in client_addr, socklen_t size);
        void            close_listenfd();
        void            close_connfd();
        int             read_buffer();
        void            flush_buffer();
        // get the options of fclient
        void            get_options();
        // handle options
        void            handle_options();
        // send files or file lists
        void            send_file();
        void            send_file_lists();
        void            send_to_client();
        void            write_send_buffer(std::string content);
        char*           read_file(char* file_name, int& num);

        // print the help of Server
        static void     print_help();
        void            print_path_files();
        void            show();
        void            show_listening();
        ~Server();
};